﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OWLServer.owl.tipos
{
    /// <summary>
    /// Clase que representa una propidad (propiedad de Datos) en una ontología.
    /// </summary>
    public class Propiedad : ElementoRestringido
    {
        private IList<Clase> dominios;
        private IList<Clase> rangos;
        private IList<TipoPropiedad> tipos;
        private IList<Propiedad> subPropiedades;
        private IList<Propiedad> padrePropiedades;
        private IList<Propiedad> equivalentesPropiedades;
        private IList<Propiedad> disjuntasPropiedades;

        /// <summary>
        /// Propiedades padre de esta propiedad
        /// </summary>
        public virtual IList<Propiedad> PadrePropiedades
        {
            get { return padrePropiedades; }
            set { padrePropiedades = value; }
        }

        /// <summary>
        /// Subpropiedades de esta propiedad
        /// </summary>
        public virtual IList<Propiedad> SubPropiedades
        {
            get { return subPropiedades; }
            set { subPropiedades = value; }
        }

        /// <summary>
        /// Propiedades equivalentes de esta propiedad
        /// </summary>
        public virtual IList<Propiedad> EquivalentesPropiedades
        {
            get { return equivalentesPropiedades; }
            set { equivalentesPropiedades = value; }
        }

        /// <summary>
        /// Propiedades disjuntas de esta propiedad
        /// </summary>
        public virtual IList<Propiedad> DisjuntasPropiedades
        {
            get { return disjuntasPropiedades; }
            set { disjuntasPropiedades = value; }
        }

        /// <summary>
        /// Tipos del que puede ser la propiedad
        /// </summary>
        public virtual IList<TipoPropiedad> Tipos
        {
            get { return tipos; }
            set { tipos = value; }
        }
        
        /// <summary>
        /// Clases del dominio de la propiedad
        /// </summary>
        public virtual IList<Clase> Dominios
        {
            get { return dominios; }
            set { dominios = value; }
        }

        /// <summary>
        /// Clases del rango de la propiedad
        /// </summary>
        public virtual IList<Clase> Rangos
        {
            get { return rangos; }
            set { rangos = value; }
        }

        public Propiedad() { }

        public Propiedad(string id) : base(id)
        {
            inicializarListas();
        }

        public Propiedad(string id, EspacioNombres espacioNombres)
            : base(id, espacioNombres)
        {
            inicializarListas();
        }

        public Propiedad(Elemento elemento)
            : base(elemento)
        {
            inicializarListas();
        }

        /// <summary>
        /// Inicializa las listas de elementos
        /// </summary>
        private void inicializarListas()
        {
            Tipos = new List<TipoPropiedad>();
            Dominios = new List<Clase>();
            Rangos = new List<Clase>();
            SubPropiedades = new List<Propiedad>();
            PadrePropiedades = new List<Propiedad>();
            DisjuntasPropiedades = new List<Propiedad>();
            EquivalentesPropiedades = new List<Propiedad>();
        }

        /// <summary>
        /// Devuelve la lista de rangos en un Diccionario
        /// </summary>
        /// <returns>Diccionario de rangos</returns>
        public virtual IDictionary<string, Clase> getRangosDictiorary()
        {
            return Rangos.ToDictionary(e => e.ToString(), e => e);
        }

        /// <summary>
        /// Devuelve la lista de dominios en un Diccionario
        /// </summary>
        /// <returns>Diccionario de dominios</returns>
        public virtual IDictionary<string, Clase> getDominiosDictiorary()
        {
            return Dominios.ToDictionary(e => e.ToString(), e => e);
        }

        /// <summary>
        /// Devuelve la lista de subpropiedades en un Diccionario
        /// </summary>
        /// <returns>Diccionario de subpropiedades</returns>
        public virtual IDictionary<string, Propiedad> getSubPropiedadesDictiorary()
        {
            return SubPropiedades.ToDictionary(e => e.ToString(), e => e);
        }

        /// <summary>
        /// Devuelve la lista de propiedades padre en un Diccionario
        /// </summary>
        /// <returns>Diccionario de subpropiedades</returns>
        public virtual IDictionary<string, Propiedad> getPadrePropiedadesDictiorary()
        {
            return PadrePropiedades.ToDictionary(e => e.ToString(), e => e);
        }

        /// <summary>
        /// Devuelve la lista de disjuntas en un Diccionario
        /// </summary>
        /// <returns>Diccionario de disjuntas</returns>
        public virtual IDictionary<string, Propiedad> getDisjuntasPropiedadesDictiorary()
        {
            return DisjuntasPropiedades.ToDictionary(e => e.ToString(), e => e);
        }

        /// <summary>
        /// Devuelve la lista de dequivalentes en un Diccionario
        /// </summary>
        /// <returns>Diccionario de disjuntas</returns>
        public virtual IDictionary<string, Propiedad> getEquivalentesPropiedadesDictiorary()
        {
            return EquivalentesPropiedades.ToDictionary(e => e.ToString(), e => e);
        }
    }

    /// <summary>
    /// Tipo de propiedades que se le pueden aplicar a una propiedad
    /// </summary>
    public enum TipoPropiedad : int
    {
        FUNCIONAL,
        INVERSA_FUNCIONAL,
        TRANSITIVA,
        SIMETRICA,
        ASIMETRICA,
        REFLEXIVA,
        IRREFLEXIVA
    }
}
